package org.example;


import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;

import java.security.*;
import org.bitcoinj.core.Base58;

import org.bouncycastle.jce.ECNamedCurveTable;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;



import java.math.BigInteger;

import java.security.*;

import java.security.spec.ECParameterSpec;

import java.util.Arrays;
public class Main {

    private static String BITCOIN_NETWORK_VERSION = "0x01";

    public static String bytesToHex(byte[] bytes) {

        StringBuilder sb = new StringBuilder();

        for (byte b : bytes) {

            sb.append(String.format("%02X", b));

        }

        return sb.toString();

    }


    public static void main(String[] args) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException {

        // 添加Bouncy Castle作为安全提供程序

        Security.addProvider(new BouncyCastleProvider());

        // 使用指定的曲线参数创建密钥对生成器

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");

        ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1");

        keyPairGenerator.initialize(ecSpec, new SecureRandom());



        // 生成密钥对

        KeyPair keyPair = keyPairGenerator.generateKeyPair();



        // 获取私钥和公钥

        byte[] privateKey = keyPair.getPrivate().getEncoded();

        PublicKey publicKey = keyPair.getPublic();

        System.out.println("privateKey:"+bytesToHex(privateKey));

        System.out.println("publicKey:"+bytesToHex(publicKey.getEncoded()));
        byte[] publicKeyBytes = publicKey.getEncoded();



        // 对公钥进行SHA-256哈希，然后进行RIPEMD-160哈希

        byte[] publicKeyHash = ripemd160(sha256(publicKeyBytes));



        // 将比特币网络版本号附加到哈希值前面

        byte[] networkVersionAndHash = appendVersion(publicKeyHash);



        // 计算校验和

        byte[] checkSum = calculateChecksum(networkVersionAndHash);



        // 将校验和附加到网络版本号和哈希值后面

        byte[] addressBytes = appendChecksum(networkVersionAndHash, checkSum);



        // 对字节数组进行Base58编码

        String bitcoinAddress = Base58.encode(addressBytes);



        System.out.println("Bitcoin Address: " + bitcoinAddress);
    }
    private static byte[] sha256(byte[] input) throws NoSuchAlgorithmException {

        MessageDigest digest = MessageDigest.getInstance("SHA-256");

        return digest.digest(input);

    }



    private static byte[] ripemd160(byte[] input) {

        // 实际应用中需要实现RIPEMD-160哈希算法

        // 这里仅作为示例，返回一个固定的哈希值

        return new byte[20]; // 替换为实际的RIPEMD-160哈希结果

    }



    private static byte[] calculateChecksum(byte[] data) throws NoSuchAlgorithmException {

        MessageDigest digest = MessageDigest.getInstance("SHA-256");

        digest.update(digest.digest(data));

        return Arrays.copyOf(digest.digest(), 4);

    }



    private static byte[] appendVersion(byte[] hash) {

        BITCOIN_NETWORK_VERSION = BITCOIN_NETWORK_VERSION.substring(2);

        // 移除 "0x" 前缀



        BigInteger version = new BigInteger(BITCOIN_NETWORK_VERSION, 16);

        byte[] versionBytes = version.toByteArray();

        byte[] networkVersionAndHash = new byte[versionBytes.length + hash.length];

        System.arraycopy(versionBytes, 0, networkVersionAndHash, 0, versionBytes.length);

        System.arraycopy(hash, 0, networkVersionAndHash, versionBytes.length, hash.length);

        return networkVersionAndHash;

    }



    private static byte[] appendChecksum(byte[] data, byte[] checksum) {

        byte[] dataWithChecksum = new byte[data.length + checksum.length];

        System.arraycopy(data, 0, dataWithChecksum, 0, data.length);

        System.arraycopy(checksum, 0, dataWithChecksum, data.length, checksum.length);

        return dataWithChecksum;

    }
}